package de.tu_darmstadt.gdi1.xcom.tests.testcases.students;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import org.junit.Before;
import org.junit.Test;

import de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel2;
import de.tu_darmstadt.gdi1.xcom.tests.testcases.students.TestLevel;

/**
 * 
 * Tests if shooting-actions are performed correctly
 * 
 * @author Lukas Schwoebel
 *
 */
public class KITests {
	
	private XcomTestAdapterLevel2 testAdapter;
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testAdapter = new XcomTestAdapterLevel2();
	}
	
	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel2#performKIAction()}.
	 */
	@Test
	public final void testKIActionCostsTheSame() {

		testAdapter.loadLevelFromString(TestLevel.saveGame1);
		
		// rotating costs
		testAdapter.performKIAction("2;2;r");
		assertTrue("Rotating an alien should cost 1 actionpoint,\n" + testAdapter.returnGamestateAsSavegame(),
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;2;2;s;50;74;50;0;0") >= 0));
		testAdapter.performKIAction("3;2;l");
		assertTrue("Rotating an alien should cost 1 actionpoint,\n" + testAdapter.returnGamestateAsSavegame(),
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;3;2;w;50;74;50;0;0") >= 0));
		
		// walking costs
		testAdapter.performKIAction("3;2;r");
		testAdapter.performKIAction("3;2;f");
		assertTrue("Walking for an alien should cost 3 actionpoints,\n" + testAdapter.returnGamestateAsSavegame(),
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;3;1;n;50;70;50;0;0") >= 0));
		
		// attacking costs
		testAdapter.performKIAction("2;2;l"); // 73
		testAdapter.performKIAction("2;2;f"); // 70
		testAdapter.performKIAction("3;2;a"); // 60
		assertTrue("Attacking for an alien should cost 10 actionpoints,\n" + testAdapter.returnGamestateAsSavegame(),
				(testAdapter.returnGamestateAsSavegame().indexOf("//Z;3;2;e;50;60;50;0;0") >= 0));
	}
	
	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel2#performKIAction()}.
	 */
	@Test
	public final void testKIHandledCorrectly() {
		
		testAdapter.loadLevelFromString(TestLevel.saveGame1);
		
		// do a KI-action
		testAdapter.performKIAction("2;2;l");
		testAdapter.performKIAction("2;2;a");
		
		assertEquals("The KI just killed the player on 2:1", '.', testAdapter.elementOnPosition(2, 1));
		
		String kiGameState1 = "" +
			"############\n" +
			"##...#######\n" +
			"##...##...##\n" +
			"###.###...##\n" +
			"###.####.###\n" +
			"#....##...##\n" +
			"#.........##\n" +
			"############\n" +
			"//{mobs}\n" +
			"//@;4;2;e;40;75;34;49;8\n" +
			"//@;2;5;w;30;60;50;50;11\n" +
			"//@;4;6;s;50;75;50;50;3\n" +
			"//Z;2;2;n;50;64;50;0;0\n" +
			"//Z;3;2;n;50;75;50;0;0\n" +
			"//Z;7;3;n;50;75;50;0;0\n" +
			"//Z;7;5;n;50;75;50;0;0\n" +
			"//Z;9;6;n;50;75;50;0;0\n" +
			"//{gamedata}\n" +
			"//activeteam:Z\n" +
			"//playedrounds:0\n" +
			"//maxrounds:2";
		

		String returnedSavegame = testAdapter.returnGamestateAsSavegame();
		// replace doors-line if there is any and remove any additional info if there is any
		returnedSavegame = returnedSavegame.replaceFirst("(?m)//\\{doors\\}\n", "");
		returnedSavegame = returnedSavegame.replaceFirst("(?s)//maxrounds:2(.*)$", "//maxrounds:2");
		
		assertEquals("The gamestate after two KI actions was not like expected", kiGameState1, returnedSavegame);
		
		// decrementing action-points of alien a bit
		for(int i = 0; i < 52; i++) {
			testAdapter.performKIAction("9;6;l");
		}
		testAdapter.performKIAction("9;6;l");
		testAdapter.performKIAction("9;6;f");
		
		// test if alien moved
		assertEquals("The alien von 9:6 should have moved to 8:6", '.', testAdapter.elementOnPosition(9, 6));
		assertEquals("The alien von 9:6 should have moved to 8:6", 'Z', testAdapter.elementOnPosition(8, 6));
		
		testAdapter.performKIAction("8;6;f");
		testAdapter.performKIAction("7;6;f");
		testAdapter.performKIAction("6;6;f");
		testAdapter.performKIAction("5;6;f");
		
		// only forward-action, should not be executed
		assertEquals("The alien should not kill with forward-actions, the player at 4:6 should still exist", '@', testAdapter.elementOnPosition(4, 6));
		assertEquals("The alien should not have moved as on 4:6 there is a player", 'Z', testAdapter.elementOnPosition(5, 6));
		
		// now try to kill with attack-action
		testAdapter.performKIAction("5;6;a");
		assertEquals("The alien should have killed the player at 4:6", '.', testAdapter.elementOnPosition(4, 6));

		String kiGameState2 = "" +
			"############\n" +
			"##...#######\n" +
			"##...##...##\n" +
			"###.###...##\n" +
			"###.####.###\n" +
			"#....##...##\n" +
			"#.........##\n" +
			"############\n" +
			"//{mobs}\n" +
			"//@;4;2;e;40;75;34;49;8\n" +
			"//@;2;5;w;30;60;50;50;11\n" +
			"//Z;2;2;n;50;64;50;0;0\n" +
			"//Z;3;2;n;50;75;50;0;0\n" +
			"//Z;7;3;n;50;75;50;0;0\n" +
			"//Z;7;5;n;50;75;50;0;0\n" +
			"//Z;5;6;w;50;0;50;0;0\n" +
			"//{gamedata}\n" +
			"//activeteam:Z\n" +
			"//playedrounds:0\n" +
			"//maxrounds:2";

		returnedSavegame = testAdapter.returnGamestateAsSavegame();
		// replace doors-line if there is any and remove any additional info if there is any
		returnedSavegame = returnedSavegame.replaceFirst("(?m)//\\{doors\\}\n", "");
		returnedSavegame = returnedSavegame.replaceFirst("(?s)//maxrounds:2(.*)$", "//maxrounds:2");
		
		assertEquals("The gamestate after ki-actions was not like expected", kiGameState2, returnedSavegame);
		
		// now try to walk or rotate alien, should not be possible with no actionpoints left
		testAdapter.performKIAction("5;6;f");
		testAdapter.performKIAction("5;6;l");

		returnedSavegame = testAdapter.returnGamestateAsSavegame();
		// replace doors-line if there is any and remove any additional info if there is any
		returnedSavegame = returnedSavegame.replaceFirst("(?m)//\\{doors\\}\n", "");
		returnedSavegame = returnedSavegame.replaceFirst("(?s)//maxrounds:2(.*)$", "//maxrounds:2");
		
		// gamestate should not have changed
		assertEquals("The gamestate was not like expected, no actionpoints left for alien -- there should be no change",
				kiGameState2, returnedSavegame);
	}
	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel2#turnsLeft()}.
	 */
	@Test
	public final void testKIActionInflectTurns() {
		
		testAdapter.loadLevelFromString(TestLevel.saveGame1);
				
		// do some action with first active player
		testAdapter.performActionForActivePlayer();
		testAdapter.rotateActivePlayer(true);
		testAdapter.rotateActivePlayer(true);
		
		assertEquals("There should be 2 turns left to play", 2, testAdapter.turnsLeft());
		
		// now perform KI-actions
		testAdapter.performKIAction("7;5;r");
		testAdapter.performKIAction("7;5;f");
		testAdapter.performKIAction("9;6;f");
		
		assertEquals("Even after KI-actions, still 2 turns should be left to play", 2, testAdapter.turnsLeft());
	}
}
